use crate::hystrix::metriccollector::MetricResult;
use crate::hystrix::metrics::MetricCollector;
use crate::hystrix::rolling::timing::Timing;
use crate::Number;

pub struct DefaultMetricCollector {
    num_requests:Number,
    errors:Number,

    successes:Number,
    failures:Number,
    rejects:Number,
    short_circuits:Number,
    timeouts:Number,
    context_canceled:Number,
    context_deadline_exceeded:Number,

    fallback_successes:Number,
    fallback_failures:Number,
    total_duration:Timing,
    run_duration:Timing,
}


impl Default for DefaultMetricCollector {
    fn default() -> Self {
        let mut m = DefaultMetricCollector{
            num_requests: Default::default(),
            errors: Default::default(),
            successes: Default::default(),
            failures: Default::default(),
            rejects: Default::default(),
            short_circuits: Default::default(),
            timeouts: Default::default(),
            context_canceled: Default::default(),
            context_deadline_exceeded: Default::default(),
            fallback_successes: Default::default(),
            fallback_failures: Default::default(),
            total_duration: Default::default(),
            run_duration: Default::default()
        };

        m
    }
}

impl MetricCollector for  DefaultMetricCollector {
    fn update(&mut self, data: MetricResult) {
        self.num_requests.increment(data.Attempts);
        self.errors.increment(data.Errors);
        self.successes.increment(data.Successes);
        self.failures.increment(data.Failures);
        self.rejects.increment(data.Rejects);
        self.short_circuits.increment(data.ShortCircuits);
        self.timeouts.increment(data.Timeouts);
        self.fallback_successes.increment(data.FallbackSuccesses);
        self.fallback_failures.increment(data.FallbackFailures);
        self.context_canceled.increment(data.ContextCanceled);
        self.context_deadline_exceeded.increment(data.ContextDeadlineExceeded);

        self.total_duration.add(data.TotalDuration);
        self.run_duration.add(data.RunDuration);
    }

    fn reset(&mut self) {
        *self = DefaultMetricCollector::default();
    }
}

impl DefaultMetricCollector {
    pub fn run_duration(&self) ->&Timing {
        &self.run_duration
    }

    pub fn total_duration(&self) -> &Timing {
        &self.total_duration
    }
}

